package org.sdnstproject.interlayer.openflowfuzzing;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class StrategesGen {
	private static final Logger log = LoggerFactory.getLogger(StrategesGen.class);
	static StringBuilder builder = new StringBuilder();
	public static ArrayList<String> StrategesGenerate(){
		ArrayList<String> strateges = new ArrayList<>();
		//TODO
		return strateges;
	}
	
	public static ArrayList<String> packetStraGen(String ofVersion, String ofType) {
		String childOFType = "*";
		String action = "*";
		String field = "*";
		String actionValue = "*";
		ArrayList<String> stras = new ArrayList<String>();
		OF13MsgFields of13MsgFields = new OF13MsgFields();
		stras.add(straBuilder(ofVersion,ofType,childOFType,"DROP",field,actionValue));
		stras.add(straBuilder(ofVersion,ofType,childOFType,"DELAY",field,"100"));
		stras.add(straBuilder(ofVersion,ofType,childOFType,"DELAY",field,"1000"));
		stras.add(straBuilder(ofVersion,ofType,childOFType,"DUPLICATE",field,"2"));
		stras.add(straBuilder(ofVersion,ofType,childOFType,"DUPLICATE",field,"10"));
		Iterator<Entry<String, String>> iterator = of13MsgFields.portStatusMsgFields.entrySet().iterator();
		while (iterator.hasNext()) {
			field = iterator.next().getKey();
			String fieldType = iterator.next().getValue();
			for (String ss : getValofModify(fieldType)) {
				actionValue = ss;
				stras.add(straBuilder(ofVersion,ofType,childOFType,"MODIFY",field,actionValue));
			}
		}
		return stras;
	}
	
	public static String straBuilder(String ofVersion,String ofType,String childOFType,String action,String field,String actionValue) {
		builder.append("ofVersion:").append(ofVersion).append(",ofType:").append(ofType)
		.append(",childOFType:").append(childOFType).append(",action:").append(action)
		.append(",field:").append(field).append(",actionValue:").append(actionValue);
		String stra = builder.toString();
		builder.delete(0, builder.length());
		return stra;
	}
	
	public static void printToFile(ArrayList<String> stra, String file) {
		FileWriter fileWriter = null;
		BufferedWriter bufferedWriter = null;
		try {
			fileWriter = new FileWriter(file);
			bufferedWriter =new BufferedWriter(fileWriter);
			for(String s:stra) {
				bufferedWriter.write(s);
				bufferedWriter.write('\n');
			}
			bufferedWriter.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(bufferedWriter != null) {
				try {
					bufferedWriter.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void readFromFile(ArrayList<String> stra, String file) {
		FileReader fileReader = null;
		BufferedReader bufferedReader = null;
		try {
			fileReader = new FileReader(file);
			bufferedReader =new BufferedReader(fileReader);
			String line = null;
			while((line = bufferedReader.readLine()) != null) {
				stra.add(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private static String[] getValofModify(String fieldType) {
		switch (fieldType) {
		case "byte":
			return new String[] { "0", "128", "255" };
		case "short":
			return new String[] { "0", "32000", "65535" };
		case "int":
			return new String[] { "0", "65535", "4294967295" };
		case "long":
			return new String[] { "0", "65535", "42949672954", "8882949672954" };
		case "String":
			return new String[] { "", "0", "000000000", "fffffffff" };
		default:
			return new String[] { "0", "1", "2" };// 负数？
		}
	}

	
	/*ofVersion:"+ofVersion+",ofType:"+ofType+",childOFType:"+childOFType
				+",action:"+action+",field:"+field+",actionValue:"+actionValue
	 * */
	public static Strategy getStrategyObject(String stra) {
		String[] stras = stra.split(",");
		if(stras.length != 6) {
			log.info("please check the strategy!");
			return null;
		}
		String ofVersion = null;
		String ofType = null;
		String childOFType = null;
		String action = null;
		String field = null;
		String actionValue = null;
		for(String ss:stras) {
			String[] st = ss.split(":");
			if(st.length != 2) {
				log.info("please check the strategy!");
				return null;
			}
			switch (st[0]) {
			case "ofVersion":
				ofVersion = st[1];
				break;
			case "ofType":
				ofType = st[1];
				break;
			case "childOFType":
				childOFType = st[1];
				break;
			case "action":
				action = st[1];
				break;
			case "field":
				field = st[1];
				break;
			case "actionValue":
				actionValue = st[1];
				break;
			}
		}
		return new Strategy(ofVersion, ofType, childOFType, action, field, actionValue);
	}
}
